home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 May: Tool Chest / Dev.CD May 98 TC.toast / Tool Chest / Development Kits / HyperCard Related / APDA HyperCard Toolkits / HyperCard CTB Toolkit 1.0b2 / Source Code / CTBRecvUpTo.p < prev    next >
Encoding:
Text File  |  1995-02-07  |  8.6 KB  |  288 lines  |  [TEXT/MPS ]

  1. (*
  2.     CTBRecvUpTo([termChar[,timeOut[,limit[,dontStrip]]]]) -- Receive characters until the termChar is
  3.         received, or until timeOut 60ths of a second have passed. If the limit parameter is present, then
  4.         only receive that many characters maximum. If the dontStrip parameter is present, then don't
  5.         do control character or top bit stripping. If CTBRecvUpTo is called with no parameters, and it
  6.         was previously called and returned due to reaching the character limit, then it will continue the
  7.         previous receive with the same termChar, timeOut, limit, and dontStrip settings.
  8.  
  9.     To compile and link this file using Macintosh Programmer's Workshop,
  10.  
  11.         pascal -w CTBRecvUpTo.p
  12.         link -m ENTRYPOINT -o HyperCommands -rt XFCN=2760 -sn Main=CTBRecvUpTo ∂
  13.             CTBRecvUpTo.p.o "{MPW}"Libraries:interface.o "{MPW}"Libraries:Libraries:HyperXLib.o
  14.  
  15.     © Copyright 1990 by Apple Computer, Inc.
  16.  
  17.     Initial coding 2/90 by Harry R. Chesley.
  18. *)
  19.  
  20. {$R-}
  21.  
  22. {$S CTBRecvUpTo }     { Segment name must be the same as the command name. }
  23.  
  24. unit DummyUnit;
  25.  
  26. interface
  27.  
  28. uses MemTypes, QuickDraw, OSIntf, ToolIntf, CTBUtils, FTIntf, CMIntf, TMIntf, CRMIntf, HyperXCmd;
  29.  
  30. procedure EntryPoint(paramPtr: XCmdPtr);
  31.     
  32. implementation
  33.  
  34. procedure CTBRecvUpTo(paramPtr: XCmdPtr); forward;
  35.  
  36. procedure EntryPoint(paramPtr: XCmdPtr);
  37.  
  38.     begin
  39.         CTBRecvUpTo(paramPtr);
  40.     end;
  41.  
  42. procedure CTBRecvUpTo(paramPtr: XCmdPtr);
  43.  
  44.     {$I CTBUtil.inc}
  45.  
  46.     var lookForTerm: boolean;
  47.         termString: Ptr;
  48.         termPtr, oldTermPtr: Ptr;
  49.         stopAt: longInt;
  50.         doStrip: boolean;
  51.         gotIt: boolean;
  52.         toRead: longInt;
  53.         toCopy: longInt;
  54.         oldSize: longInt;
  55.         l, l2, l3: longInt;
  56.         h: Handle;
  57.         p: Ptr;
  58.         sizes: CMBufferSizes;
  59.         status: CMStatFlags;
  60.         theBuf: InputBufferHandle;
  61.         recvMax: longInt;
  62.  
  63.     procedure Fail(errMsg: Str255); { set theResult and quit }
  64.         begin
  65.             if lookForTerm then HUnlock(paramPtr^.params[1]);
  66.             paramPtr^.returnValue := PasToZero(paramPtr,errMsg);
  67.             exit(CTBRecvUpTo);
  68.         end;
  69.  
  70.     begin
  71.         { Check the number of parameters. }
  72.         if paramPtr^.paramCount > 4 then Fail('Invalid parameter count');
  73.  
  74.         { Check that the Comm Toolbox is ready. }
  75.         CTBReady;
  76.         { And that we've got a connection tool. }
  77.         EnsurePresent(connectionTool);
  78.         { And it's open. }
  79.         EnsureOpen;
  80.         theBuf := InputBufferHandle(CMGetUserData(Globals^^.connHand));
  81.  
  82.         { Are we getting the next part due to a limit return? }
  83.         if paramPtr^.paramCount = 0 then
  84.             begin
  85.                 if theBuf^^.timeOut = -1 then exit(CTBRecvUpTo);
  86.                 { If so, then load the parameters from the saved globals. }
  87.                 if theBuf^^.termString <> nil then
  88.                     begin
  89.                         lookForTerm := true;
  90.                         HLock(theBuf^^.termString);
  91.                         termString := theBuf^^.termString^;
  92.                         termPtr := Ptr(ord4(termString)+theBuf^^.termOffset);
  93.                     end
  94.                 else lookForTerm := false;
  95.             end
  96.         else
  97.             begin
  98.                 { If there's parameters already loaded, clear it out. }
  99.                 if theBuf^^.termString <> nil then
  100.                     begin
  101.                         DisposHandle(theBuf^^.termString);
  102.                         theBuf^^.termString := nil;
  103.                     end;
  104.                 { Get the termination string. }
  105.                 if ParmPresent(1) then
  106.                     begin
  107.                         theBuf^^.termString := paramPtr^.params[1];
  108.                         if HandToHand(theBuf^^.termString) <> noErr then
  109.                             begin
  110.                                 theBuf^^.termString := nil;
  111.                                 Fail('Could not allocate string space');
  112.                             end;
  113.                         lookForTerm := true;
  114.                         HLock(theBuf^^.termString);
  115.                         termString := theBuf^^.termString^;
  116.                         termPtr := termString;
  117.                     end
  118.                 else lookForTerm := false;
  119.                 { Get the time-out. }
  120.                 if ParmPresent(2) then theBuf^^.timeOut := GetLongParm(2)
  121.                 else theBuf^^.timeOut := 0;
  122.                 { Get the character limit. }
  123.                 if ParmPresent(3) then theBuf^^.recvLimit := GetLongParm(3)
  124.                 else theBuf^^.recvLimit := 50000;
  125.                 { Find out if we should strip. }
  126.                 if ParmPresent(4) then theBuf^^.doStrip := false
  127.                 else theBuf^^.doStrip := true;
  128.             end;
  129.  
  130.         { Get all the parameters into easy-to-access form. }
  131.         recvMax := theBuf^^.recvLimit;
  132.         stopAt := TickCount + theBuf^^.timeOut;
  133.         doStrip := theBuf^^.doStrip;
  134.  
  135.         { Allocate a results handle. }
  136.         h := NewHandle(0);
  137.         if h = nil then Fail('Out of memory');
  138.  
  139.         { Loop 'til we drop. }
  140.         gotIt := false;
  141.         repeat
  142.             { If there's nothing left in the buffer, read more in. }
  143.             if theBuf^^.amountLeft = 0 then
  144.                 begin
  145.                     { But only if there's something to read. }
  146.                     if CMStatus(Globals^^.connHand,sizes,status) = noErr then
  147.                         begin
  148.                             if BAnd(status,cmStatusOpening+cmStatusListenPend+cmStatusIncomingCallPresent+
  149.                                             cmStatusOpen) = 0 then leave;
  150.                             toRead := min(sizes[cmDataIn],BUFFERSIZE)
  151.                         end
  152.                     else toRead := 0;
  153.                     if toRead > 0 then toRead := ReadFromConn(@theBuf^^.buffer,toRead);
  154.                     theBuf^^.bufferPtr := @theBuf^^.buffer;
  155.                     theBuf^^.amountLeft := toRead;
  156.                 end;
  157.  
  158.             { If there's anything to process, process it. }
  159.             if theBuf^^.amountLeft > 0 then
  160.                 begin
  161.                     { Check for the termination string. }
  162.                     if lookForTerm then
  163.                         begin
  164.                             p := theBuf^^.bufferPtr;
  165.                             l := min(recvMax,theBuf^^.amountLeft);
  166.                             { Decide whether to loop and strip or just loop and look. Note: We have to strip now
  167.                                 rather than after we've read everything because the termination string matches
  168.                                 the data after it's been striped. }
  169.                             if doStrip then
  170.                                 while l > 0 do
  171.                                     begin
  172.                                         l := l-1;
  173.                                         if BAnd(p^,$7F) = termPtr^ then
  174.                                             begin
  175.                                                 termPtr := Ptr(ord4(termPtr)+1);
  176.                                                 if termPtr^ = 0 then
  177.                                                     begin
  178.                                                         gotIt := true;
  179.                                                         leave;
  180.                                                     end;
  181.                                             end
  182.                                         else
  183.                                             begin
  184.                                                 { If not, then recalculate where we are in the termination string. }
  185.                                                 l2 := ord4(termPtr)-ord4(termString)-1;
  186.                                                 oldTermPtr := termPtr;
  187.                                                 termPtr := termString;
  188.                                                 while l2 > 0 do
  189.                                                     begin
  190.                                                         p := Ptr(ord4(oldTermPtr)-l2);
  191.                                                         l3 := l2;
  192.                                                         while l3 > 0 do
  193.                                                             begin
  194.                                                                 if p^ <> termPtr^ then leave;
  195.                                                                 p := Ptr(ord4(p)+1);
  196.                                                                 termPtr := Ptr(ord4(termPtr)+1);
  197.                                                                 l3 := l3-1;
  198.                                                             end;
  199.                                                         if (l3 = 0) and (BAnd(p^,$7F) = termPtr^) then leave;
  200.                                                         l2 := l2-1;
  201.                                                         termPtr := termString;
  202.                                                     end;
  203.                                                 if BAnd(p^,$7F) = termPtr^ then termPtr := Ptr(ord4(termPtr)+1)
  204.                                                 else termPtr := termString;
  205.                                             end;
  206.                                         p := Ptr(ord4(p)+1);
  207.                                     end
  208.                             else
  209.                                 while l > 0 do
  210.                                     begin
  211.                                         l := l-1;
  212.                                         if p^ = termPtr^ then
  213.                                             begin
  214.                                                 termPtr := Ptr(ord4(termPtr)+1);
  215.                                                 if termPtr^ = 0 then
  216.                                                     begin
  217.                                                         gotIt := true;
  218.                                                         leave;
  219.                                                     end;
  220.                                             end
  221.                                         else
  222.                                             begin
  223.                                                 { If not, then recalculate where we are in the termination string. }
  224.                                                 l2 := ord4(termPtr)-ord4(termString)-1;
  225.                                                 oldTermPtr := termPtr;
  226.                                                 termPtr := termString;
  227.                                                 while l2 > 0 do
  228.                                                     begin
  229.                                                         p := Ptr(ord4(oldTermPtr)-l2);
  230.                                                         l3 := l2;
  231.                                                         while l3 > 0 do
  232.                                                             begin
  233.                                                                 if p^ <> termPtr^ then leave;
  234.                                                                 p := Ptr(ord4(p)+1);
  235.                                                                 termPtr := Ptr(ord4(termPtr)+1);
  236.                                                                 l3 := l3-1;
  237.                                                             end;
  238.                                                         if (l3 = 0) and (p^ = termPtr^) then leave;
  239.                                                         l2 := l2-1;
  240.                                                         termPtr := termString;
  241.                                                     end;
  242.                                                 if p^ = termPtr^ then termPtr := Ptr(ord4(termPtr)+1)
  243.                                                 else termPtr := termString;
  244.                                             end;
  245.                                         p := Ptr(ord4(p)+1);
  246.                                     end;
  247.                         end
  248.                     else l := 0;
  249.                     { Copy over whatever fits. }
  250.                     oldSize := GetHandleSize(h);
  251.                     toCopy := min(recvMax,theBuf^^.amountLeft) - l;
  252.                     SetHandleSize(h,oldSize + toCopy);
  253.                     if MemError <> noErr then
  254.                         begin
  255.                             DisposHandle(h);
  256.                             Fail('Out of memory');
  257.                         end;
  258.                     BlockMove(theBuf^^.bufferPtr,Ptr(ord4(h^) + oldSize),toCopy);
  259.                     theBuf^^.bufferPtr := Ptr(ord4(theBuf^^.bufferPtr) + toCopy);
  260.                     theBuf^^.amountLeft := theBuf^^.amountLeft - toCopy;
  261.                     recvMax := recvMax - toCopy;
  262.                     stopAt := TickCount + theBuf^^.timeOut;
  263.                 end
  264.             else if (TickCount - stopAt) > 0 then leave;
  265.  
  266.         until gotIt or (recvMax = 0);
  267.  
  268.         { Unlock the termination string buffer. }
  269.         if lookForTerm then HUnlock(theBuf^^.termString);
  270.  
  271.         { If we saw the termination, get rid of the termination/time-out information. }
  272.         if gotIt then
  273.             begin
  274.                 theBuf^^.timeOut := -1;
  275.                 DisposHandle(theBuf^^.termString);
  276.                 theBuf^^.termString := nil;
  277.             end
  278.         { Otherwise, remember it. }
  279.         else theBuf^^.termOffset := ord4(termPtr)-ord4(termString);
  280.  
  281.         { Strip the results and return it. }
  282.         StripBytes(h,GetHandleSize(h),doStrip);
  283.  
  284.         paramPtr^.returnValue := h;
  285.     end;
  286.  
  287. end.
  288.